package com.xiuyou.tracksdk.http;



import android.content.Context;
import android.util.Log;

import com.xiuyou.tracksdk.tracksdk.module.BaseResult;
import com.xiuyou.tracksdk.tracksdk.module.HistoryPoint;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * httpClitent 
 * 该类都是子线程操作并未支持主线程自动切换,建议handler更新主线程
 * @author liuha
 *
 */
public class HttpManager {
	HttpClient client = null;
	HttpPost httpPost = null;
	HttpGet httpGet = null;
	private String charset = "UTF-8";
	HttpResponse response = null;
	private static HttpManager INSTANCE = null;
	List<NameValuePair> httpParams = null;
	private int connectTimeout = 1000 * 15; // 连接超时时间
	private ExecutorService executorService = null;
	private Context mcontext = null;
	public static HttpManager getInstance(Context mcontext){
		if(INSTANCE == null){
			synchronized (HttpManager.class) {
				if(INSTANCE == null){
					INSTANCE = new HttpManager(mcontext);
				}
			}
		}
		return INSTANCE;
	}

	public HttpManager(Context mcontext){
		client = new DefaultHttpClient();
		HttpParams params = client.getParams();
		//设置超时间
		params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, connectTimeout);
		//在提交请求之前 测试连接是否可用 
		params.setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false);
		//初始化一个单线程
		executorService = Executors.newSingleThreadExecutor();
		this.mcontext = mcontext;
	}

	/**
	 * 普通post请求
	 * @param url
	 * @param params
	 * @param baseCallback
	 * @param responseParams
     * @param <T>
     */
	public <T> void doPost(final String url, final Map<String,String> params,
						   final BaseCallback<T> baseCallback, final ResponseParams responseParams){
		executorService.submit(new Runnable() {
			
			@Override
			public void run() {
				post(url,params,baseCallback,responseParams);
			}
		});
	}
	
	public <T> void doGetInputSteam(final String url, final Map<String,String> params,
									final BaseCallback<T> baseCallback, final ResponseParams responseParams){
		executorService.submit(new Runnable() {
			
			@Override
			public void run() {
				getInputSteam(url,params,baseCallback,responseParams);
			}
		});
	}

	/**
	 * 普通get请求
	 * @param <T>
	 * @param url
	 * @param params
	 * @param baseCallback
	 * @param responseParams
	 */
	public <T> void doGet(final String url, final Map<String,String> params,
						  final BaseCallback baseCallback, final ResponseParams responseParams){
		executorService.submit(new Runnable() {
			
			@Override
			public void run() {
				get(url,params,baseCallback,responseParams);
			}
		});
	}

	/**
	 * get请求 获取流信息
	 * @param url
	 * @param params
	 * @param baseCallback
	 * @param responseParams
     * @param <T>
     */
	private <T> void getInputSteam(String url, Map<String,String> params, BaseCallback<T> baseCallback, ResponseParams responseParams){
		String lastPath = "";
		String path = null;
		if(params != null && params.size() > 0){
			lastPath = "?";
			for (Map.Entry<String, String> entry : params.entrySet()) {
				lastPath +=  entry.getKey() + "=" + entry.getValue() + "&" ;
			}
			lastPath = lastPath.substring(0, lastPath.length()-1);
		}
		path = url+lastPath;
		httpGet = new HttpGet(path);
		InputStream inputStream=null;
		try {
			response = client.execute(httpGet);
			inputStream = response.getEntity().getContent();
			T t = (T) inputStream;
			baseCallback.sucess(t);
		} catch (Exception e) {
			dealException(baseCallback,e);
		}finally{
			if (httpGet != null) {
				httpGet.abort();
			}
			IOUtils.closeQuietly(inputStream);
		}
	}

	private <T> void get(String url, Map<String,String> params, BaseCallback<T> baseCallback, ResponseParams responseParams){
		String lastPath = "";
		String path = null;
		if(params != null && params.size() > 0){
			lastPath = "?";
			for (Map.Entry<String, String> entry : params.entrySet()) {
				lastPath +=  entry.getKey() + "=" + entry.getValue() + "&" ;
			}
			lastPath = lastPath.substring(0, lastPath.length()-1);
		}
		path = url+lastPath;
		Log.e("path is",path);
		httpGet = new HttpGet(path);
		InputStream inputStream=null;
		try {
			response = client.execute(httpGet);
			inputStream = response.getEntity().getContent();
			dealResult(baseCallback,responseParams,inputStream);
		} catch (Exception e) {
			dealException(baseCallback,e);
			e.printStackTrace();
		}finally{
			if (httpGet != null) {
				httpGet.abort();
			}
			IOUtils.closeQuietly(inputStream);
		}
	}

	private <T> void post(String url, Map<String,String> params, BaseCallback<T> baseCallback, ResponseParams responseParams){
		httpPost = new HttpPost(url);
		httpParams = new ArrayList<NameValuePair>();
		if(params != null && params.size() > 0){
			for (Map.Entry<String, String> entry : params.entrySet()) {
				httpParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
			}
		}InputStream inputStream = null;
		 try {
			 httpPost.setEntity(new UrlEncodedFormEntity(httpParams, charset));
			 response = client.execute(httpPost);
			 inputStream = response.getEntity().getContent();
			 dealResult(baseCallback,responseParams,inputStream);
		 } catch (Exception e) {
			 dealException(baseCallback,e);
		}finally{
			if (httpPost != null) {
				httpPost.abort();
			}
			IOUtils.closeQuietly(inputStream);
		}
	}
	
	private <T> void dealResult(BaseCallback<T> baseCallback, ResponseParams responseParams, InputStream inputStream ) throws Exception {
		Log.e("response status is",response.getStatusLine().getReasonPhrase());
		 if (200 == response.getStatusLine().getStatusCode()){
			 if(inputStream != null){
				String contStr = getResponseConnt(inputStream);
				@SuppressWarnings("unchecked")
				T t = (T) responseParams.parse(contStr);
				baseCallback.sucess(t);
			 }
		 }else{
			 errorServer(baseCallback,response.getStatusLine().getStatusCode());
		 }
	}
	
	private String getResponseConnt(InputStream inputStream) throws Exception {
		BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, charset));
		StringBuilder sb = new StringBuilder();
		String line = "";
		while ((line = reader.readLine()) != null) {
			sb.append(line).append("\n");
		}
		return sb.toString().trim();
	};
	
	/**
	 * 目前处理两种异常 
	 * SERVER_REJECT 服务器拒绝访问
	 * TIME_OUT 连接超时
	 * @param baseCallback
	 * @param e
	 * @return
	 */
	private <T> void dealException(BaseCallback<T> baseCallback,Exception e){
		Log.e("错误异常",e.getMessage());
		String exceptionName = e.getClass().getSimpleName();
		if(exceptionName.equals(ErrorMethod.SERVER_REJECT.getKey())){
			baseCallback.error(e, ErrorMethod.SERVER_REJECT.getValue());
		}else if(exceptionName.equals(ErrorMethod.TIME_OUT.getKey())){
			baseCallback.error(e, ErrorMethod.TIME_OUT.getValue());
		}else{
			baseCallback.error(e, ErrorMethod.OTHRE_EXCEPTION.getValue());
		}
	}
	/**
	 * 该方法主要处理除200外的异常
	 * 目前处理 404 和 500 异常
	 * @param baseCallback
	 * @param code
	 */
	private <T> void errorServer(BaseCallback<T> baseCallback,int code){
		switch (code) {
		case 404:
			baseCallback.serverError(ErrorMethod.SERVER_ERROR_404.getValue());
			break;
		case 500:
			baseCallback.serverError(ErrorMethod.SERVER_ERROR_500.getValue());
			break;
		default:
			baseCallback.serverError(ErrorMethod.SERVER_ERROR_OTHER.getValue());
			break;
		}
	}
}
